package 面向对象;
/*
  内部类 
  内部类可以独立地继承一个(接口)的实现，不管外部类是否继承实现某个接口，内部类不受影响，所以内部类可以有效的实现"多重继承"
  1，成员内部类<成员>:直接在类里定义的类
      通过外部类.内部类 表示，通过 外部类实例.new内部类() 实例化内部类
  2，方法内部类<局部>:在一个类中的方法中定义一个类
      a.方法内部类只能在方法内部实例化(只在方法体{}内有效)
	  b.方法内部类对象不能使用该内部类所在方法的非final局部变量
  3，静态内部类<成员>:在一个类中定义的一个静态的内部类
      a.同静态方法一样，无法访问外部类非静态变量和方法
  4，匿名内部类<局部>:没有名字的内部类
      a.继承式  b.接口式   c.参数式
	  原则:a.不能有构造方法，只能有一个实例
	      b.不能定义任何静态成员(变量和方法)
		  c.不能是 public protected private static修饰
		  d.一定是在new后面，用其隐含实现一个类或接口
		  e,匿名内部类属于局部，局部内部类的限制同样对其有效
*/
public class 内部类
{
	public static void main(String[] args){
		Outer outer=new Outer("hoho");//产生外部类实例
		//一般不建议这样生成内部类实例
		Outer.Inner inner=outer.new Inner();//产生内部类实例
		inner.print();
		//通常通过封装的方法调用内部类
		outer.innerPrint();
		//调用方法中的内部类
		outer.show();
		//静态内部类不依赖外部类对象
		Outer.Inner1 inner1=new Outer.Inner1();
		inner1.print();
		//匿名内部类
		outer.print1();
		outer.print2();
		//参数式匿名内部类写法
		outer.print3(new Eat(){

				@Override
				public void eat()
				{
					System.out.println("参数式匿名内部类");
				}
				
			
		});
		
	}
}

class Outer{
	private String name;
	public Outer(String name){
		this.name=name;
	}
	//一般内部类不向外暴露，提供方法访问
	public void innerPrint(){
		Inner inner=new Inner();
		System.out.println("通过封装方法访问内部类.....");
		inner.print();
	}
	//=========成员内部类==========
	//建议加private 避免外部实例化
	class Inner{
		public void print(){
			System.out.println("成员内部类......"+name);
		}
	}
	//=========静态内部类========
	//主要用在封装
	static class Inner1{
		public void print(){
			System.out.println("静态内部类");
		}
	}
	//========方法内部类========
	public void show(){
		//final int x=10;//不加final编译出错(jdk 1.8final可省略但也必须是常量)
		class Inner2{
			public void print(){
				System.out.println("方法内部类");
			}
		}
		Inner2 inner2=new Inner2();
		inner2.print();
	}
	//=========匿名内部类========
	//继承式
	public void print1(){
		Cat cat=new Cat(){

			@Override
			public void eat()
			{
				System.out.println("继承式匿名内部类");
			}
		};
		cat.eat();
	}
	//接口式
	public void print2(){
		Eat eat=new Eat(){

			@Override
			public void eat()
			{
				System.out.println("接口式匿名内部类");
			}
		};
		eat.eat();
	}
	//参数式匿名内部类
	public void print3(Eat eat){//只写参数，调用时写内部类
		eat.eat();
	}
}
interface Eat{
	void eat();
}
abstract class Cat{
	public abstract void eat();
}
